home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / dskutil / ideinf10.zip / IDEINFO.C < prev    next >
C/C++ Source or Header  |  1994-08-03  |  15KB  |  409 lines

  1. /*
  2. IDEINFO.EXE
  3.  
  4. Tries to tell all about all IDE drives, including ATA-2 stuff.
  5.  
  6. Copyright (c) July 1994 by Raimo Koski - All rights reserved
  7. Postal Address: Uudenmaantie 23 K 3
  8.                 20720
  9.                 Finland
  10.  
  11. Compiles with BC++ 3.1
  12. */
  13.  
  14.  
  15. #include <stdlib.h>
  16. #include <ctype.h>
  17. #include <dos.h>
  18. #include <stdio.h>
  19. #include <conio.h>
  20. #include <bios.h>
  21. #include <io.h>
  22. #include <fcntl.h>
  23. #include <string.h>
  24. #include <sys\stat.h>
  25. #include "ideinfo.h"
  26.  
  27. #define TIME_OUT 600000
  28. /* Was 100 000 but with one 33 MHz 486DX it was too little in about
  29.    haft of the runs. I reasoned that 100 MHz Pentium would be about
  30.    6 times as fast and 600 000 would be on the verge of being too
  31.    little but that is the worst case currently.
  32.    Raise the value if all drives are not found in a very fast machine
  33. */
  34.  
  35. #define MAX_FILE 99             // Max number of files, increase if needed,
  36.                                 // big value slows down.
  37.  
  38. char *getascii (unsigned int in_data [], int off_start, int off_end);
  39. void prtinfo(int loop);
  40. void usage(void);
  41. unsigned int htoi(char *s);
  42.  
  43. unsigned int dd [256]; /* DiskData */
  44. unsigned int dd_off;   /* DiskData offset */
  45. unsigned int bios_cyl [2], bios_head [2], bios_sec [2];  /* Cylinders, Heads, Sectors */
  46. int cntr;               // Number of controllers we try
  47. unsigned int cntl_base[4] = {0x1f0, 0x170, 0xf0, 0x70};  // Try all ususal ports
  48. int stdout_tty;
  49. int no_cntr = 1;
  50. int R_file = 0;
  51.  
  52.  
  53. void main (void)
  54. {
  55.   unsigned int loop, extloop;     /* Loop variable */
  56.   int num_drv;           /* Number of BIOS Hard disks */
  57.   int max_cntr = 4;
  58.   int handle, i, j, di;
  59.   int wrote = 0;
  60.   int retry = 0;
  61.  
  62.   char ext[3];
  63.   char filename[13];
  64.   union REGS registers;  /* Used for Interrupt for BIOS data */
  65.  
  66.   clrscr ();
  67.   stdout_tty =  isatty(fileno(stdout));
  68.  
  69.   for (i=0;i < _argc; i++)
  70.      if ((strcmpi(_argv[i], "/H") == 0) || (strcmpi(_argv[i], "-H") == 0) ||
  71.          (strcmpi(_argv[i], "H" ) == 0) || (strcmpi(_argv[i], "/?") == 0) ||
  72.          (strcmpi(_argv[i], "-?") == 0) || (strcmpi(_argv[i], "?" ) == 0))
  73.         usage();
  74.  
  75.      for (i=0;i < _argc; i++)
  76. // Search for F parameter, if found write drive info to file
  77.         if ((strcmpi(_argv[i], "/F") == 0) || (strcmpi(_argv[i], "-F") == 0) || (strcmpi(_argv[i], "F") == 0))
  78.            R_file = 1;
  79.  
  80.  
  81. // If R (Read) parameter is given display all idedrive.* files in current
  82. // directory, then quit.
  83.   for (i=0;i < _argc; i++)
  84.      if ((strcmpi(_argv[i], "/R") == 0) || (strcmpi(_argv[i], "-R") == 0) || (strcmpi(_argv[i], "R") == 0))
  85.      {
  86.         bios_head [0] = 0;
  87.         bios_sec [0] = 0;
  88.         bios_cyl [0] = 0;
  89.         _fmode = O_BINARY;
  90.         loop = 0;
  91.         do
  92.         {
  93.            /* change the default file mode from text to binary */
  94.            itoa(loop, ext, 10);
  95.            strcpy(filename, "idedrive.");
  96.            strcat(filename, ext);
  97.            handle = open(filename, O_RDONLY);
  98.            if (handle == -1)
  99.               continue;
  100.            read(handle, dd, 512);
  101.            close(handle);
  102.            no_cntr = 0;
  103.            prtinfo(0);
  104.         }
  105. // Could be larger but I guess that 100 files is enough for a while
  106.         while (loop++ < MAX_FILE);
  107.         return(0);
  108.      }
  109.  
  110.   /* How many disk drives & parameters */
  111. // Try even if not defined in BIOS
  112.   num_drv = 2;
  113.  
  114. //Trust BIOS
  115. //num_drv = peekb (0x40, 0x75);  /* BIOS Data area, Number of Hard disks */
  116.                                  /* Byte at Segment 40H Offset 75H */
  117.  
  118.  
  119.   j = 0;
  120.   for (i=0;i < _argc; i++)
  121.      if ((strcmpi(_argv[i], "/P") == 0) || (strcmpi(_argv[i], "-P") == 0) || (strcmpi(_argv[i], "P") == 0))
  122.      {
  123.         cntl_base[j++] = htoi(_argv[i+1]);
  124. //      printf("%3x\n", cntl_base[j]);
  125.         if (cntl_base[cntr] == 0) continue;
  126. // Sanity check, room only for 4 addresses.
  127.         if (j==3) break;
  128.         max_cntr = j;
  129.      };
  130.  
  131.  
  132.   for (cntr = 0; cntr < max_cntr; cntr++)
  133.   {
  134.      for (loop = 0; loop < num_drv; loop++)  /* Loop through drives */
  135.      {
  136.         di = 0;
  137.         retry = TIME_OUT;
  138.  /* Wait for controller not busy or timeout */
  139.         while ((di != 0x50) && (--retry))
  140.            di = inp(cntl_base[cntr] + HD_STATUS);
  141.         if (!retry)
  142.         // timed out
  143.         {
  144.            if (!R_file)
  145.            {
  146.               fprintf (stdout, "\nAdapter %1u at %3xh not found\n", cntr, cntl_base[cntr]);
  147.               fprintf (stdout, "Last status %2xh\n", di);
  148.               if (stdout_tty)
  149.               {
  150.                  fprintf (stderr, "Press a key\n");
  151.                  getch ();
  152.               }
  153.            }
  154.         // This adapter is done ie. not existing
  155.            goto outerloop;
  156.         }
  157.         /* Get first/second drive */
  158.         outp (cntl_base[cntr] + HD_CURRENT, (loop == 0 ? 0xA0 : 0xB0));
  159.         /* Get drive info data */
  160.         outp (cntl_base[cntr] + HD_COMMAND, 0xEC);
  161.         retry = TIME_OUT;
  162.         di = 0;
  163.         /* Wait for data ready or time out*/
  164.         while ((di != 0x58) && (--retry))
  165.            di = inp(cntl_base[cntr] + HD_STATUS);
  166.         if (!retry)
  167.         {
  168.         // Timed out
  169.            if  (!R_file)
  170.            {
  171.               fprintf (stdout, "\nAdapter %1u at %3xh Drive %1u not found\n", cntr, cntl_base[cntr], loop);
  172.               fprintf (stdout, "Last status %2xh\n", di);
  173.               if (stdout_tty)
  174.               {
  175.                  fprintf (stderr, "Press a key\n");
  176.                  getch ();
  177.               }
  178.            }
  179.         // reselect drive 0
  180.            if (loop) outp (cntl_base[cntr] + HD_CURRENT, 0xa0);
  181.            continue;
  182.         }
  183.  
  184.         for (dd_off = 0; dd_off != 256; dd_off++) /* Read "sector" */
  185.            dd [dd_off] = inpw (cntl_base[cntr] + HD_DATA);
  186.  
  187.         if (R_file)
  188.         {
  189.            extloop = 0;
  190. // Loop file extensions until we find unused one
  191.            do
  192.            {
  193.            /* change the default file mode from text to binary */
  194.               _fmode = O_BINARY;
  195.               itoa(extloop, ext, 10);
  196.               strcpy(filename, "idedrive.");
  197.               strcat(filename, ext);
  198.               handle = open(filename, O_RDONLY);
  199.               close(handle);
  200.            }
  201.            while ((handle != -1) && (extloop++ < MAX_FILE));
  202. // Exit if too many files
  203.            if (extloop > MAX_FILE) return(0);
  204.  
  205.         /* create a binary file for writing */
  206.            handle = creat(filename, S_IWRITE);
  207.         /* write 512 bytes to the file */
  208.            write(handle, dd, 512);
  209.  
  210.               /* close the file */
  211.            close(handle);
  212.            wrote = 1;
  213.            fprintf (stdout, "Wrote info for DRIVE %d Adapter %1u at base address %3xh to file %s\n",
  214.               loop, cntr, cntl_base[cntr], filename);
  215.         }
  216. // Trust BIOS only with default primary adapter
  217.         if (cntl_base[cntr] == 0x1f0)
  218.         {
  219.            /* Get BIOS drive info */
  220.            registers.h.ah = 0x8;            /* Get drive info */
  221.            registers.h.dl = 0x80 + loop;    /* Drive is 80H for Disk 0, 81H for Disk 1 */
  222.            int86 (0x13, ®isters, ®isters);
  223.            if (! registers.x.cflag)   /* All OK if carry not set */
  224.            {
  225.               bios_head [loop] = registers.h.dh + 1; /* Heads are from 0 */
  226.               bios_sec [loop] = registers.h.cl & 0x3F; /* sec is bits 5 - 0 */
  227.               bios_cyl [loop] = ((registers.h.cl & 0xC0) << 2) + registers.h.ch + 2; /* +1 because starts from 0 and +1 for FDISK leaving one out */
  228.            }
  229.         }
  230.         else
  231.         {
  232.            bios_head [loop] = 0;
  233.            bios_sec [loop] = 0;
  234.            bios_cyl [loop] = 0;
  235.         }
  236.         if (wrote==0) prtinfo(loop);
  237.      }
  238. outerloop:
  239.   }
  240. }
  241.  
  242.  
  243. void prtinfo(int loop)
  244. {
  245.   clrscr ();
  246.   if (no_cntr) fprintf (stdout, "DRIVE %d Adapter %1u at base address %3xh\n",
  247.         loop, cntr, cntl_base[cntr]);
  248.   fprintf (stdout, "                        Disk Reports    BIOS Reports\n");
  249.   fprintf (stdout, "                    Default     Current\n");
  250.   fprintf (stdout, "# of Cylinders______:%4u\t %4i\t %4u\n",
  251.         dd [1], (dd[53] & 1) ? dd[54] : -1, bios_cyl [loop]);
  252.   fprintf (stdout, "# of Heads__________:%4u\t %4i\t %4u\n",
  253.         dd [3], (dd[53] & 1) ? dd[55] : -1, bios_head [loop]);
  254.   fprintf (stdout, "# of Sectors/Track__:%4u\t %4i\t %4u\n",
  255.         dd [6], (dd[53] & 1) ? dd[56] : -1, bios_sec [loop]);
  256.   fprintf (stdout, "Model Number________: %s\n", getascii (dd, 27, 46));
  257.   fprintf (stdout, "Serial Number_______: %s\n", getascii (dd, 10, 19));
  258.   fprintf (stdout, "Controller Rev. #___: %s\n", getascii (dd, 23, 26));
  259.   fprintf (stdout, "Double Word Transfer: %6s\n",
  260.         (dd [48] == 0 ? "No" : "Yes"));
  261.   fprintf (stdout, "Controller type_____: ");
  262.   if(dd [20]== 0) fprintf (stdout,"Not specified/Unknown\n");
  263.   if(dd [20]== 1) {
  264.      fprintf (stdout,"a single ported single sector buffer which is not capable of\n");
  265.      fprintf (stdout,"\t\t      simultaneous data transfers to or from the host and the disk.");
  266.   }
  267.   if(dd [20]== 2) {
  268.      fprintf (stdout,"a dual ported multi-sector buffer capable of simultaneous\n");
  269.      fprintf (stdout,"\t\t      data transfers to or from the host and the disk.\n");
  270.   }
  271.   if(dd [20]== 3) {
  272.      fprintf (stdout,"a dual ported multi-sector buffer capable of simultaneous\n");
  273.      fprintf (stdout,"\t\t      transfers with a read caching capability.\n");
  274.   }
  275.   if(dd [20] > 3) fprintf (stdout,"Reserved/Unknown\n");
  276.   fprintf (stdout, "Buffer size (kB)____: %6u\n", dd [21] >>1);
  277.   fprintf (stdout, "# of ECC bytes______: %6u\n", dd [22]);
  278.   fprintf (stdout, "# of secs/interrupt_: %6u", 0xff & dd [47]);
  279.   if (dd [59] & 256)
  280.      fprintf (stdout, "\tCurrent setting %3u\n",0xff & dd[59]);
  281.   else fprintf (stdout, "\n");
  282.   fprintf (stdout, "LBA support\t\t %s",(dd [49] & 512) ? "Yes" : " No");
  283.   if (dd [49] & 512){
  284.      fprintf (stdout, "%6.1fMB of LBA addressable",
  285.         (((float)dd[61]* 65536 + (float) dd[60]) / 2048));
  286.      if (dd[53] & 1) fprintf (stdout, " %6.1fMB in CHS mode\n",
  287.         (((float)dd[58]* 65536 + (float) dd[57]) / 2048));
  288.      }
  289.   else fprintf (stdout, "\n");
  290.   fprintf (stdout, "DMA support\t\t %s\n",  (dd [49] & 256) ? "Yes" : " No");
  291.   fprintf (stdout, "IORDY supported\t\t %s\nIORDY can be disabled\t %s\n",
  292.         (dd[49] & 2048) ? "Yes" : " No",(dd [49] & 1024) ? "Yes" : " No");
  293.   fprintf (stdout, "PIO data txfer cycle timing mode:  %6u\n",
  294.         (0xff00 & dd [51]) >> 8);
  295.   if (dd [49] & 256)
  296.      if ((dd[62] + dd[63]) == 0)  // if words 62 and 63 supported ignore 53
  297.         fprintf (stdout, "SW DMA txfer cycle timing mode:    %6u  \n" ,
  298.            (0xff00 & dd [52]) >> 8);
  299.      else
  300.      {
  301.         fprintf (stdout, "SW DMA txfer cycle timing modes:\t");
  302.         switch(0x00ff & dd [62]) {
  303.            case 0x0004 : fprintf(stdout, "2");
  304.            case 0x0002 : fprintf(stdout, "1");
  305.            case 0x0001 : fprintf(stdout, "0");
  306.            default:      fprintf(stdout, " ");
  307.         }
  308.         fprintf (stdout, "    Active ");
  309.         switch(0xff00 & dd [62]) {
  310.            case 0x0400 : fprintf(stdout, "2\n"); break;
  311.            case 0x0200 : fprintf(stdout, "1\n"); break;
  312.            case 0x0100 : fprintf(stdout, "0\n"); break;
  313.            default:      fprintf(stdout, "\n");
  314.         }
  315.         fprintf (stdout, "MW DMA txfer cycle timing modes:\t");
  316.         switch(0x00ff & dd [63]) {
  317.            case 0x0004 : fprintf(stdout, "2");
  318.            case 0x0002 : fprintf(stdout, "1");
  319.            case 0x0001 : fprintf(stdout, "0");
  320.            default:      fprintf(stdout, " ");
  321.         }
  322.         fprintf (stdout, "   Active ");
  323.         switch(0xff00 & dd [63]) {
  324.            case 0x0400 : fprintf(stdout, "2\n"); break;
  325.            case 0x0200 : fprintf(stdout, "1\n"); break;
  326.            case 0x0100 : fprintf(stdout, "0\n"); break;
  327.            default:      fprintf(stdout, "\n");
  328.         }
  329.      }
  330.   if (dd [53] & 2){
  331.      if (stdout_tty)
  332.      {
  333.         fprintf (stdout, "Press a key\n");
  334.         getch ();
  335.      }
  336.      fprintf (stdout, "Congratulations, your drive supports ATA-2\n");
  337.      fprintf (stdout, "Advanced PIO txfer modes supported:\t\t ");
  338.      switch(0x00ff & dd [64]) {
  339.         case 0x0004 : fprintf(stdout, "5");
  340.         case 0x0002 : fprintf(stdout, "4");
  341.         case 0x0001 : fprintf(stdout, "3");
  342.         default:      fprintf(stdout, "\n");
  343.         }
  344.      fprintf (stdout, "Min MW DMA txfer cycle time/word:             %4u ns   %2.1fMB/s\n",
  345.         dd [65], 1/(float)dd[65]*2e3);
  346.      fprintf (stdout, "Mfg Recommended MW DMA txfer Cycle Time       %4u ns   %2.1fMB/s\n",
  347.         dd [66], 1/(float)dd[66]*2e3);
  348.      fprintf (stdout, "Min PIO txfer Cycle Time w/o Flow Control     %4u ns   %2.1fMB/s\n",
  349.         dd [67], 1/(float)dd[67]*2e3);
  350.      fprintf (stdout, "Min PIO txfer Cycle Time w IORDY Flow Control %4u ns   %2.1fMB/s\n",
  351.         dd [68], 1/(float)dd[68]*2e3);
  352.   }
  353.   else fprintf (stdout, "Sorry, no ATA-2 features implemented\n");
  354.   if (stdout_tty)
  355.   {
  356.      fprintf (stdout, "Press a key\n");
  357.      getch ();
  358.   }
  359. }
  360.  
  361.  
  362. char *getascii (unsigned int in_data [], int off_start, int off_end)
  363. {
  364.   static char ret_val [255];
  365.   int loop, loop1;
  366.  
  367.   for (loop = off_start, loop1 = 0; loop <= off_end; loop++)
  368.     {
  369.       ret_val [loop1++] = (char) (in_data [loop] / 256);  /* Get High byte */
  370.       ret_val [loop1++] = (char) (in_data [loop] % 256);  /* Get Low byte */
  371.     }
  372.   ret_val [loop1] = '\0';  /* Make sure it ends in a NULL character */
  373.   return (ret_val);
  374. }
  375.  
  376. unsigned int htoi(char *s)
  377. {
  378.    unsigned int i, j = 0;
  379.  
  380.    while (('\0' != *s) && isxdigit(*s))
  381.    {
  382.       i = *s++ - '0';
  383.       if (9 < i)
  384.          i -= 7;
  385.       j <<= 4;
  386.       j |= (i & 0x0f);
  387.    }
  388.    return(j);
  389. }
  390.  
  391.  
  392. void usage(void)
  393. {
  394.   fprintf (stderr, "IDEINFO [[H] || [?] || [R]] || [[F]] [P xxx] [P xxx].. ]]\n\n");
  395.   fprintf (stderr, "Version 1.0. Tries to tell all about all IDE drives, including ATA-2 stuff.\n\n");
  396.   fprintf (stderr, "Options may be preceded with -, / or none\n");
  397.   fprintf (stderr, "-H or -? prints this help.\n");
  398.   fprintf (stderr, "-R Reads idedrive.* files from current directory.\n");
  399.   fprintf (stderr, "-F Writes drive identify info to idedrive.* files to current directory.\n");
  400.   fprintf (stderr, "-P xxx looks only adapter at port xxx, xxx in hex format\n\n");
  401.   fprintf (stderr, "File extension is next available number when writing.\n\n");
  402.   fprintf (stderr, "File size is 512 bytes.\n");
  403.   fprintf (stderr, "You may redirect output.\n\n");
  404.   fprintf (stderr, "Example: Look only for adapters at 1F0h (primary) and 170h (normal secondary)\n");
  405.   fprintf (stderr, "and write info to files.\n");
  406.   fprintf (stderr, "IDEINFO P 1f0 P 170 F\n");
  407.   exit(0);
  408. }
  409.